home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1998 August / PC Plus SuperCD 50b Issue 142 (CD142b) (August 1998).iso / essent / FIXES / CSeries.exe / issue100 / CPROG15.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-31  |  6.6 KB  |  161 lines

  1. /* CPROG15.CPP - List all filenames+attributes in the current directory */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <dos.h>
  6. #include <dir.h>
  7. #include <string.h>
  8.  
  9.  
  10. //---------------------------------------------------------------------------
  11. /* The next function converts an attribute number into a string that shows
  12. more clearly which attribute flags have been set. It expects a single-byte
  13. file attribute and returns a pointer to the string. An attribute byte is
  14. bit-significant in that when its value is written in binary notation, the
  15. fifth bit from the right, for example, indicates whether or not the file
  16. is a subdirectory. 1 says it is, 0 says it isn't. Another example:
  17. File attribute=decimal 33. Binary=100001. Bit zero (the one on the right) when
  18. turned on says the file is read-only. Bit five (count from right to left,
  19. starting at zero) when turned on says this file hasn't been backed up
  20. (archived). The letters in the array attlet[] indicateethe meaning of the bit
  21. in that position when it is turned on.*/
  22.  
  23. char *makestring(char fileattribute)
  24. {
  25. static char attstring[7],      // 6 attributes + '\0'. Static so that when
  26.                  // makestring() exits, returning a pointer
  27.                  // to attstring, attstring isn't destroyed.
  28.         attlets[]= "ADLSHR"; // The letters used.
  29. int i;                 // A loop counter.
  30.  
  31.     for(i=5; i>=0; i--)    // For each of the six significant bits...
  32.         {
  33.         attstring[i]= ( fileattribute & 1 ) ? attlets[i] : '-';
  34.                 // Logical AND the attribute with 1.
  35.                 // 1 AND 1 = 1          1 AND 0 = 0.
  36.                 // So the test is only non-zero if bit 0
  37.                 // is not zero. True result causes the
  38.                 // appropriate letter in attlets[] to be
  39.                 // put in attstring[]. False result gives '-'
  40.         fileattribute=fileattribute >> 1;
  41.                 // The >> operator shifts all the bits to the
  42.                 // right by the number of places indicated by
  43.                 // the following number. eg: 11011 becomes
  44.                 // 1101 - the rightmost bit is lost. We do
  45.                 // this so that the bit we're interested in
  46.                 // is always in position zero, making the
  47.                 // fileattribute & 1 always the correct test.
  48.         }
  49.     attstring[6]='\0';      // terminate the string
  50.     return( attstring );    // return its address for use as a pointer
  51. }
  52.  
  53. //---------------------------------------------------------------------------
  54. int main(void)
  55. {
  56. struct ffblk filedetails; // Make a ffblk-type structure for findfirst()/findnext()
  57.  
  58. struct filerecord { char filename[13];        // 8 + '.' + 3 + '\0' = 13 chars
  59.             char attribute;        // 1 byte for the attribute
  60.             struct filerecord *previous;  // Pointer to previous structure in chain of records. Will be 0 if this is top of list
  61.             struct filerecord *next;    // Pointer to next record in list. Will be 0 if this is bottom.
  62.             };
  63. /* A filerecord-type structure has room for the filename, its attribute plus
  64. two structure pointers - one to the previous structure in the list,
  65. one to the next. */
  66.  
  67. struct filerecord *firstrec, *temp, *current;
  68.                 // Could have included these in the declaration
  69.                 // of filerecord above. Did it as a separate
  70.                 // line for clarity. Current will hold a pointer
  71.                 // to whichever filerecord-type structure
  72.                 // we're dealing with currently. Firstrec will
  73.                 // point to the first in the list so we always
  74.                 // have a record of the start of the chain. Temp
  75.                 // is needed as a temporary place holder.
  76.  
  77.      /*    Use findfirst()/findnext() to get list of files in current directory
  78.     into memory. Create new storage records as required. */
  79.  
  80.     if( findfirst("*.*", &filedetails, FA_RDONLY+FA_HIDDEN+FA_SYSTEM+FA_LABEL+FA_DIREC+FA_ARCH) == -1 )
  81.         {
  82.         printf("Nothing to do!\n"); // Highly unlikely this would happen.
  83.         exit(0);
  84.         }
  85.      /* Point of interest: in binary, 10000+00001=10001. 10001+00100=10101.
  86.     Adding together all possible flags produces a number in which all
  87.     flags are set on, so all files will be found - even the weird ones
  88.     that are normally hidden. More about FA_RDONLY etc at bottom. */
  89.  
  90.     temp=firstrec=0; // 0 in firstrec later triggers its intialisation.
  91.             // Temp needs to start out as zero - it will become
  92.             // the first pointer to the previous structure. Since
  93.             // the first structure has nowhere to point, putting
  94.             // zero in *previous indictates to later program code
  95.             // threading backwards up the chain that it has
  96.             // reached the top.
  97.  
  98.      /* Neat bit of C++ syntax is that you can say x=y=z=number, and number
  99.     goes into x, y and z. */
  100.  
  101.      // Read filenames, create and fill structures
  102.     do {
  103.         if( ! (current=new filerecord) ) // Make a new structure
  104.             {
  105.             printf("Oh dear, we're clean out of spare bytes!\n");
  106.             exit(0);
  107.             }
  108.  
  109.         if( firstrec == 0 )
  110.             firstrec=current; // Initialise firstrec to point to
  111.                       // first strcucture in list.
  112.  
  113.         // Fill in the new record
  114.         strcpy( current->filename, filedetails.ff_name ); // Copy name
  115.         current->attribute = filedetails.ff_attrib; // Copy attribute
  116.         current->previous=temp; // temp stores previous value of current
  117.         if ( temp )              // If this isn't the top of the
  118.                         // list (ie temp is not zero) then...
  119.             temp->next=current; // Make the previous *next pointer
  120.                         // point forward to this structure
  121.         temp=current;            // Make temp point here so that
  122.                         // next time round the loop we can
  123.                         // fill in the *next pointer.
  124.  
  125.     } while( ! findnext(&filedetails) ); // Loop while there are files
  126.  
  127.     current->next=0;            // And end the chain.
  128.     printf("A=Archive bit set  D=Directory  L=Volume Label  S=System  H=Hidden  R=Read only");
  129.  
  130.     // Now print each record - loop while current is not zero
  131.     for( current=firstrec; current; current=current->next )
  132.         printf("%12s\tattribute:%s\n", current->filename, makestring(current->attribute) );
  133.  
  134.              /* %12s pads the filename with spaces to fill a field
  135.                  of 12 characters
  136.             \t is a tab
  137.             %s picks up pointer to attrstring[] returned
  138.                by makestring */
  139.  
  140.     exit(-1);
  141. }
  142.  
  143. /* NOTES
  144. 1: I found these #define values (set up in DOS.H) in the help system...
  145.  
  146.     FA_RDONLY     Read-only attribute
  147.     FA_HIDDEN     Hidden file
  148.     FA_SYSTEM     System file
  149.     FA_LABEL      Volume label
  150.     FA_DIREC      Directory
  151.     FA_ARCH       Archive
  152.  
  153. The attribute parameter for findfirst() filters out all files that
  154. haven't got the selected attribute set (except in the case of 0 which also
  155. picks up files that have just the attribute set. Adding togther all possible
  156. attributes gives all files.
  157. 2: It's all easier than it looks - strip out the comments and there isn't
  158. much code here.
  159. 3: Exercise for the reader: pause output a screen at a time, printing the
  160. help line each time round and a 'Press a key' message.
  161. */